﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml.Serialization;
using BrainTechLLC.ThreadSafeObjects;
using System.Reflection;
using System.Runtime.Serialization;
using System.Xml;

namespace BrainTechLLC
{
    /// <summary>
    /// Static class to aid in/perform XML serialization
    /// </summary>
    public static class XmlSerializers
    {
        private static Dictionary<Type, XmlSerializer> _xmlSerializers = new Dictionary<Type, XmlSerializer>();
        private static XmlSerializer lastSerializer;
        private static Type lastType;

        public static XmlSerializer GetXmlSerializer(this Type t)
        {
            if (lastType == t) return lastSerializer;

            XmlSerializer serializer;
            if (!_xmlSerializers.TryGetValue(t, out serializer))
            {
                serializer = new XmlSerializer(t);
                try { _xmlSerializers.Add(t, serializer); }
                catch { }
            }

            lastType = t;
            lastSerializer = serializer;
            return serializer;
        }

        public static object DeserializeFromXml(this string xmlInput, Type objectType)
        {
            XmlSerializer xs = objectType.GetXmlSerializer();
            using (StringReader sr = new StringReader(xmlInput))
            {
                return xs.Deserialize(sr);
            }
        }

        public static object DeserializeFromCompressedXml(this byte[] xmlInputBytes, Type objectType)
        {
            byte[] decomp = xmlInputBytes.Decompress();
            string xmlInput = Encoding.UTF8.GetString(decomp);
            XmlSerializer xs = objectType.GetXmlSerializer();
            using (StringReader sr = new StringReader(xmlInput))
            {
                return xs.Deserialize(sr);
            }
        }

        public static byte[] SerializeToCompressedXml(this object o, Type objectType)
        {
            byte[] data;
            StringBuilder sb = new StringBuilder(1024);
            string xml = SerializeToXml(o, objectType, sb);
            data = Encoding.UTF8.GetBytes(xml);
            return data.Compress();
        }

        public static string SerializeToXml(this object o, Type objectType)
        {
            StringBuilder sb = new StringBuilder(1024);
            return SerializeToXml(o, objectType, sb);
        }

        public static string SerializeToXmlDC(this object o, Type objectType, params Type[] otherTypes)
        {
            StringBuilder sb = new StringBuilder(1024);
            return SerializeToXmlDC(o, objectType, sb, otherTypes);
        }


        public static string SerializeToXmlDC(this object o, Type objectType, StringBuilder sb, params Type[] otherTypes)
        {
            string xmlString = string.Empty;

            if (otherTypes == null)
                otherTypes = Type.EmptyTypes;

            DataContractSerializer xs = new DataContractSerializer(objectType, otherTypes);
            using (XmlWriter writer = XmlWriter.Create(sb, new XmlWriterSettings() { Encoding = Encoding.UTF8, ConformanceLevel = ConformanceLevel.Document, CheckCharacters = false }))
            {
                try { xs.WriteObject(writer, o); }
                catch { throw; }
            }

            return sb.ToString();
        }

        public static string SerializeToXml(this object o, Type objectType, StringBuilder sb)
        {
            string xmlString = string.Empty;
            XmlSerializer xs = objectType.GetXmlSerializer();

            using (StringWriter sw = new StringWriter(sb))
            {
                try { xs.Serialize(sw, o); }
                catch { throw; }
            }

            return sb.ToString();
        }
    }
}
